package com.hqyj.finance.server.bill.financebill.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import cn.hutool.poi.excel.cell.CellSetter;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hqyj.finance.server.bill.financebill.entity.UserExpenses;
import com.hqyj.finance.server.bill.financebill.mapper.UserExpensesMapper;
import com.hqyj.finance.server.bill.financebill.service.QiniuService;
import com.hqyj.finance.server.bill.financebill.service.UserExpensesService;
import com.hqyj.finance.server.bill.financebill.views.UserExpenseCatalogMonthsCharts;
import com.hqyj.finance.server.bill.financebill.views.UserExpenseMonthsCharts;
import com.hqyj.finance.server.bill.financebill.views.UserExpenseMonthsView;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class UserExpensesServiceImpl extends ServiceImpl<UserExpensesMapper, UserExpenses> implements UserExpensesService {

    @Value("${myproject.perPageSize}")
    private Integer perPageSize;

    @Value("${myproject.exportPath}")
    private String exportTempPath;

    @Resource
    private UserExpensesMapper userExpensesMapper;

    @Resource
    private QiniuService qiniuService;

    @Transactional(rollbackOn = Exception.class)
    @Override
    public boolean saveUserExpensesInfo(UserExpenses userExpenses) throws Exception {
        try {
            return super.save(userExpenses);
        } catch (Exception ex) {
            ex.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }
    }

    @Override
    public List<UserExpenses> queryUserExpensesInfoByUid(Integer uid) throws Exception {
        QueryWrapper<UserExpenses> queryWrapper = new QueryWrapper<UserExpenses>();
        queryWrapper.eq("expensesUserId", uid);
        return super.list(queryWrapper);
    }

    @Override
    public Page<UserExpenses> queryUserExpensePagerByUid(Integer uid, Integer currentPageNum) throws Exception {

        Page<UserExpenses> userExpensesPage = new Page<UserExpenses>(currentPageNum, perPageSize);
        QueryWrapper<UserExpenses> expensesQueryWrapper = new QueryWrapper<UserExpenses>();
        expensesQueryWrapper.eq("expensesUserId", uid);
        return userExpensesMapper.selectPage(userExpensesPage, expensesQueryWrapper);
    }

    @Override
    public UserExpenses queryUserExpenseInfoByExpensesId(Integer id) {
        return super.getById(id);
    }

    @Override
    public UserExpenseMonthsView queryUserExpenseMonthsViewByUid(Integer uid, String realName, String month, Integer currentPageNum) {
        UserExpenseMonthsView userExpenseMonthsView = new UserExpenseMonthsView();
        userExpenseMonthsView.setUid(uid);
        userExpenseMonthsView.setMonths(month);
        userExpenseMonthsView.setRealName(realName);

        Page<UserExpenses> page = new Page<UserExpenses>(currentPageNum, perPageSize);
        QueryWrapper<UserExpenses> queryWrapper = new QueryWrapper<UserExpenses>();
        queryWrapper.eq("expensesUserId", uid);
        queryWrapper.like("expensesTime", month);
        queryWrapper.orderByAsc("expensesTime");

        Page<UserExpenses> pager = userExpensesMapper.selectPage(page, queryWrapper);
        List<UserExpenses> userExpensesList = super.list(queryWrapper);

        if (userExpensesList != null && userExpensesList.size() > 0) {
            double totalFee = 0;
            for (UserExpenses expenses : userExpensesList) {
                totalFee += Double.parseDouble(expenses.getExpensesNum());
            }
            userExpenseMonthsView.setTotalFee(totalFee);
        }

        userExpenseMonthsView.setUserExpensesList(userExpensesList);
        userExpenseMonthsView.setUserExpensesPage(pager);
        return userExpenseMonthsView;
    }


    private List<List<String>> UserExpensListConvertToExcelRows(List<UserExpenses> userExpensesList, List<List<String>> rows) {
        for (UserExpenses userExpenses : userExpensesList) {
            List<String> row1 = CollUtil.newArrayList(userExpenses.getExpensesId().toString(), userExpenses.getExpensesTime(), userExpenses.getExpensesUserId().toString(), userExpenses.getExpensesUser(), userExpenses.getExpensesNum(), userExpenses.getExpensesSort(), userExpenses.getExpensesRemark(), userExpenses.getVoucherUrl());
            rows.add(row1);
        }
        return rows;
    }

    @Override
    public String exportUserExpenseMonthViewAsExcel(UserExpenseMonthsView userExpenseMonthsView) throws Exception {
        try {
            String destFile = this.exportTempPath + File.separator + IdUtil.fastSimpleUUID() + ".xlsx";
            // 通过工具类创建writer
            ExcelWriter writer = ExcelUtil.getWriter(destFile);
            String realName = userExpenseMonthsView.getRealName();
            String month = userExpenseMonthsView.getMonths();
            String totalFee = userExpenseMonthsView.getTotalFee().toString();
            //自定义标题别名
            writer.addHeaderAlias("expensesId", "流水号");
            writer.addHeaderAlias("expensesTime", "支出日期");
            writer.addHeaderAlias("expensesUserId", "用户编号");
            writer.addHeaderAlias("expensesUser", "姓名");
            writer.addHeaderAlias("expensesNum", "支出金额");
            writer.addHeaderAlias("expensesSort", "支出分类");
            writer.addHeaderAlias("expensesRemark", "支出备注");
            writer.addHeaderAlias("voucherUrl", "凭证");

            // 合并单元格后的标题行，使用默认标题样式
            writer.merge(7, realName + "" + month + "月支出明细表");

            List<List<String>> rows = new ArrayList<List<String>>();

            List<String> header = CollUtil.newArrayList("流水号", "支出日期", "用户编号", "姓名", "支出金额", "支出分类", "支出备注", "凭证");
            rows.add(header);

            UserExpensListConvertToExcelRows(userExpenseMonthsView.getUserExpensesList(), rows);

            writer.getSheet().setColumnWidth(1, 5000);
            writer.getSheet().setColumnWidth(5, 5000);
            writer.getSheet().setColumnWidth(6, 5000);
            writer.getSheet().setColumnWidth(7, 20000);
            // 一次性写出内容，使用默认样式，强制输出标题
            writer.write(rows, true);

            //单独再写一行，总金额
            List<Object> row = ListUtil.of((CellSetter) cell -> cell.setCellValue("支出总金额：" + totalFee));
            writer.writeRow(row);
            // 关闭writer，释放内存
            writer.close();

            return qiniuService.saveExcelFile(new File(destFile));
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    @Override
    public UserExpenseMonthsCharts queryUserExpenseMonthsChartsByUid(Integer uid, String realName, String month) {
        UserExpenseMonthsCharts userExpenseMonthsCharts = new UserExpenseMonthsCharts();
        UserExpenseMonthsView userExpenseMonthsView = queryUserExpenseMonthsViewByUid(uid, realName, month, 1);
        List<UserExpenses> userExpensesList = userExpenseMonthsView.getUserExpensesList();
        for (UserExpenses userExpenses : userExpensesList) {
            userExpenseMonthsCharts.getExpenseDateList().add(userExpenses.getExpensesTime());
            userExpenseMonthsCharts.getExpenseMoneyList().add(Double.parseDouble(userExpenses.getExpensesNum()));
        }
        return userExpenseMonthsCharts;
    }

    @Override
    public UserExpenseCatalogMonthsCharts queryUserExpenseCatalogMonthsCharts(Integer uid, String realName, String month) {
        UserExpenseCatalogMonthsCharts userExpenseCatalogMonthsCharts = new UserExpenseCatalogMonthsCharts();
        UserExpenseMonthsView userExpenseMonthsView = queryUserExpenseMonthsViewByUid(uid, realName, month, 1);

        List<UserExpenses> userExpensesList = userExpenseMonthsView.getUserExpensesList();
        Map<String, Double> map = userExpenseCatalogMonthsCharts.getExpenseCatalogMaps();
        for (UserExpenses userExpenses : userExpensesList) {
            String key = userExpenses.getExpensesSort();
            if (map.containsKey(key)) {
                map.put(key, map.get(key) + Double.parseDouble(userExpenses.getExpensesNum()));
            } else {
                map.put(key, Double.parseDouble(userExpenses.getExpensesNum()));
            }
        }
        return userExpenseCatalogMonthsCharts;
    }
}
